#pragma once
#include <wx/wx.h>
#include <wx/propgrid/propgrid.h>
#include <vector>
#include "SP.h"

//-------------------------------------------------------------------------
class CEProperties
{
public:
	CEProperties();
	~CEProperties();

	enum
	{
		PM_INT = 0,
		PM_FLOAT,
		PM_STRING,
		PM_COLOUR
	};

	bool					ValueAsString	( UINT idx, const wxString& );
	bool					ValueAsInteger	( UINT idx, int );
	bool					ValueAsFloat		( UINT idx, float );
	bool					ValueAsColour	( UINT idx, const wxColour& );


	bool					SetValue ( UINT idx, UINT type, const void* value );

	void					SetLayout( wxString layout) { m_Layout = layout; }
	wxString			GetLayout() { return m_Layout; }
	UINT					Blend( UINT type, const void*  ptrValue );


private:
	UINT								m_nValueCount;
	wxString						m_Layout;
	std::vector <UINT>		m_TypeTable;	
	std::vector <void*>		m_ValueTable;

	friend class CEPropertyGrid;
};


//-------------------------------------------------------------------------
class CEPropertyGrid : public wxPropertyGrid
{
public:
	CEPropertyGrid();

protected:
	struct DistributionFloatProperties
	{
		wxPGProperty* m_pProperties[20];
		SP::SPRawDistributionFloat* pRawDistributionFloat;
	};

	struct DistributionVectorProperties
	{
		wxPGProperty* m_pProperties[20];
		SP::SPRawDistributionVector* pRawDistributionVector;
	};

	struct VectorProperties
	{
		wxPGProperty* m_pProperties[5];
		XMFLOAT3 m_vValue;
	};

	void AppendDistributionFloat( wxString label, DistributionFloatProperties& DP );
	void UpdateDistributionFloat( DistributionFloatProperties& DP );
	FLOAT GetDistributionFloat( DistributionFloatProperties& DP );

	void AppendDistributionVector( wxString label , DistributionVectorProperties& DP );
	void UpdateDistributionVector( DistributionVectorProperties& DP );
	XMFLOAT3 DistributionGetVector( DistributionVectorProperties& DP );

	void AppendVector( wxString label, VectorProperties& VP );
	void UpdateVector( VectorProperties& VP );

private:
	virtual void OnUpdate() = 0;
	void OnPGChange( wxPropertyGridEvent& event );
	std::vector<wxPGProperty*> m_pProperty;
	DECLARE_EVENT_TABLE()
};

//-------------------------------------------------------------------------
class CEPropertiesPane : public wxPanel
{
private:
	CEPropertiesPane( wxWindow * parent );

	wxPropertyGrid* m_pPropertyGrid;

	friend CEPropertiesPane* CEGlobalCreatePropertiesPane( wxWindow* parent );
	void OnSize( wxSizeEvent& event );

	DECLARE_EVENT_TABLE()
};

//---Extension----------------------------------------------------------------------
//-- //------------//-----------//------------------------------------------------
class CEPGBlendState : public CEPropertyGrid
{
public:
	CEPGBlendState( SP::SPModuleBlendState* pModule );
	void OnUpdate();
protected:
	void SetValue( const D3D11_BLEND_DESC& desc );
	void GetValue( D3D11_BLEND_DESC& desc );
	wxPGProperty* m_pProperties[10];	
	SP::SPModuleBlendState* m_pModule;
};

//-------------------------------------------------------------------------
class CEPGDepthStencilState : public CEPropertyGrid
{
public:
	CEPGDepthStencilState( SP::SPModuleDepthStencilState* pModule );
	void OnUpdate();
protected:
	void SetValue( const D3D11_DEPTH_STENCIL_DESC& desc );
	void GetValue( D3D11_DEPTH_STENCIL_DESC& desc );
	wxPGProperty* m_pProperties[14];
	SP::SPModuleDepthStencilState* m_pModule;
};

//-------------------------------------------------------------------------
class CEPGRasterizerState : public CEPropertyGrid
{
public:
	CEPGRasterizerState( SP::SPModuleRasterizerState* pModule );
	void OnUpdate();
protected:
	void SetValue( const D3D11_RASTERIZER_DESC& desc );
	void GetVaule( D3D11_RASTERIZER_DESC& desc );
	wxPGProperty* m_pProperties[20];
	SP::SPModuleRasterizerState* m_pModule;
};

//-------------------------------------------------------------------------
class CEPGEmitterTransform : public CEPropertyGrid
{
public:
	CEPGEmitterTransform( SP::SPModuleEmitterTransform* pModule );
	void OnUpdate();

protected:
	VectorProperties m_vStart;
	VectorProperties m_vEnd;
	//wxPGProperty* m_pProperties[20];
	SP::SPModuleEmitterTransform* m_pModule;
};

//-------------------------------------------------------------------------
class CEPGEmitterRotation : public CEPGEmitterTransform
{
public:
	CEPGEmitterRotation( SP::SPModuleEmitterRotation* pModule );
};

//-------------------------------------------------------------------------
class CEPGEmitterTranslation : public CEPGEmitterTransform
{
public:
	CEPGEmitterTranslation( SP::SPModuleEmitterTranslation* pModule );
};

//-------------------------------------------------------------------------
class CEPGEmitterScale : public CEPGEmitterTransform
{
public:
	CEPGEmitterScale( SP::SPModuleEmitterScale* pModule );
};

//-------------------------------------------------------------------------
class CEPGEmitterColour : public CEPropertyGrid
{
public:
	CEPGEmitterColour( SP::SPModuleEmitterColour* pModule );
	void OnUpdate();
protected:
	SP::SPModuleEmitterColour* m_pModule;
	wxPGProperty* m_pProperties[20];
};

//-------------------------------------------------------------------------
class CEPGInitVector : public CEPropertyGrid
{
public:
	CEPGInitVector( SP::SPModuleInitVector* pModule );
	void OnUpdate();
protected:
	SP::SPModuleInitVector* m_pModule;
	wxPGProperty* m_pProperties[20];

	DistributionVectorProperties m_vConstant;
};

//-------------------------------------------------------------------------
class CEPGVectorOverLife : public CEPropertyGrid
{
public:
	CEPGVectorOverLife( SP::SPModuleVectorOverLife* pModule );
	void OnUpdate();

protected:
	SP::SPModuleVectorOverLife* m_pModule;
	wxPGProperty* m_pProperties[20];

	DistributionVectorProperties m_vStart;
	DistributionVectorProperties m_vEnd;
};

//-------------------------------------------------------------------------
class CEPGInitPos : public CEPGInitVector
{
public:
	CEPGInitPos( SP::SPModuleInitVector* pModule ) : CEPGInitVector( pModule ){}
};

class CEPGPosOverLife : public CEPGVectorOverLife
{
public:
	CEPGPosOverLife(  SP::SPModuleVectorOverLife* pModule ) : CEPGVectorOverLife( pModule ){}
};

class CEPGInitVelo : public CEPGInitVector
{
public:
	CEPGInitVelo( SP::SPModuleInitVector* pModule ) : CEPGInitVector( pModule ){}
};

class CEPGVeloOverLife : public CEPGVectorOverLife
{
public:
	CEPGVeloOverLife(  SP::SPModuleVectorOverLife* pModule ) : CEPGVectorOverLife( pModule ){}
};

class CEPGInitAccel : public CEPGInitVector
{
public:
	CEPGInitAccel( SP::SPModuleInitVector* pModule ) : CEPGInitVector( pModule ){}
};

class CEPGAccelOverLife : public CEPGVectorOverLife
{
public:
	CEPGAccelOverLife(  SP::SPModuleVectorOverLife* pModule ) : CEPGVectorOverLife( pModule ){}
};

class CEPGInitColour : public CEPGInitVector
{
public: 
	CEPGInitColour( SP::SPModuleInitVector* pModule ) : CEPGInitVector( pModule ){}
};

class CEPGColourOverLife : public CEPGVectorOverLife
{
public:
	CEPGColourOverLife( SP::SPModuleVectorOverLife* pModule ) : CEPGVectorOverLife( pModule ){}
};
//-------------------------------------------------------------------------
class CEPGInitFloat : public CEPropertyGrid
{
public:
	CEPGInitFloat( SP::SPModuleInitFloat* pModule );
	void OnUpdate();
protected:
	SP::SPModuleInitFloat* m_pModule;

	DistributionFloatProperties m_fConstant;
};

//-------------------------------------------------------------------------
class CEPGFloatOverLife : public CEPropertyGrid
{
public:
	CEPGFloatOverLife( SP::SPModuleFloatOverLife* pModule );
	void OnUpdate();

protected:
	SP::SPModuleFloatOverLife* m_pModule;
	wxPGProperty* m_pProperties[20];

	DistributionFloatProperties m_fStart;
	DistributionFloatProperties m_fEnd;
};

//-------------------------------------------------------------------------
class CEPGInitSize : public CEPGInitFloat
{
public:
	CEPGInitSize( SP::SPModuleInitFloat* pModule ) : CEPGInitFloat( pModule ){}
};

class CEPGSizeOverLife : public CEPGFloatOverLife
{
public:
	CEPGSizeOverLife(  SP::SPModuleFloatOverLife* pModule ) : CEPGFloatOverLife( pModule ){}
};

class CEPGInitAlpha : public CEPGInitFloat
{
public:
	CEPGInitAlpha( SP::SPModuleInitFloat* pModule ) : CEPGInitFloat( pModule ){}
};

class CEPGAlphaOverLife : public CEPGFloatOverLife
{
public:
	CEPGAlphaOverLife(  SP::SPModuleFloatOverLife* pModule ) : CEPGFloatOverLife( pModule ){}
};
//-------------------------------------------------------------------------

class CEPGBeamTerminal : public CEPropertyGrid
{
public:
	CEPGBeamTerminal( SP::SPModuleBeamTerminal* pModule );
	void OnUpdate();
protected:
	VectorProperties m_vCPStart;
	VectorProperties m_vSPStart;
	VectorProperties m_vCPEnd;
	VectorProperties m_vSPEnd;

	SP::SPModuleBeamTerminal* m_pModule;
	wxPGProperty* m_pProperties[20];
};

class CEPGBeamSource : public CEPGBeamTerminal
{
public:
	CEPGBeamSource( SP::SPModuleBeamSource* pMoudle )
		: CEPGBeamTerminal( pMoudle )
	{

	}
};

class CEPGBeamTarget : public CEPGBeamTerminal
{
public:
	CEPGBeamTarget( SP::SPModuleBeamTarget* pModule )
		: CEPGBeamTerminal( pModule )
	{

	}
};

class CEPGBeamWidth : public CEPropertyGrid
{
public:
};

class CEPGBeamShape : public CEPropertyGrid
{
public:
	CEPGBeamShape( SP::SPModuleBeamShape* pModule );
	void OnUpdate();
protected:
	VectorProperties m_vCenterStart;
	VectorProperties m_vCenterEnd;

	SP::SPModuleBeamShape* m_pModule;
	wxPGProperty* m_pProperties[20];
};

//-------------------------------------------------------------------------
class CEPGEmitter : public CEPropertyGrid
{
public:
	CEPGEmitter( SP::SPEmitter* pEmitter );

	void OnUpdate();
protected:
	wxPGProperty* m_pPropertiesBase[20];
	SP::SPEmitter* m_pEmitterBase;
};

//-------------------------------------------------------------------------
class CEPGEmitterMesh : public CEPGEmitter
{
public:
	CEPGEmitterMesh( SP::SPEmitterMesh* pMesh );

	void OnUpdate();
protected:
	SP::SPEmitterMesh* m_pEmitter;
	wxPGProperty* m_pProperties[20];
	wxString m_strFilePath;
};

//-------------------------------------------------------------------------
class CEPGEmitterParticle : public CEPGEmitter
{
public:
	CEPGEmitterParticle( SP::SPEmitterParticle* pEmitter );
	void OnUpdate();
protected:
	float m_flastRate;
	float m_flastLifeTime; 

	SP::SPEmitterParticle* m_pEmitter;
	wxPGProperty* m_pProperties[20];
	wxString m_strFilePath;
};

//-------------------------------------------------------------------------
class CEPGEmitterBeam : public CEPGEmitter
{
public:
	CEPGEmitterBeam( SP::SPEmitterBeam* pEmitter );
	void OnUpdate();

protected:
	SP::SPEmitterBeam* m_pEmitter;
	wxPGProperty* m_pProperties[20];
		
	wxString m_strFilePath;
};

//-------------------------------------------------------------------------
class CEPGEmitterAnimTrail : public CEPGEmitter
{
public:
	CEPGEmitterAnimTrail( SP::SPEmitterAnimTrail* pEmitter );
	void OnUpdate();

protected:
	SP::SPEmitterAnimTrail* m_pEmitter;
	wxPGProperty* m_pProperties[20];

	VectorProperties m_vLeft;
	VectorProperties m_vRight;	
	
	wxString m_strFilePath;
};